﻿using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.IO;
using Outlook = Microsoft.Office.Interop.Outlook;

namespace Qero.ChartPoint
{
    class RegisterHomepage
    {
        /// <summary> Registration ID for scripting
        /// </summary>
        private const string CATIDSafeForScripting = "7DD95801-9882-11CF-9FA9-00AA006C42C4";

        /// <summary> Registraton ID for initializing
        /// </summary>
        private const string CATIDSafeForInitializing = "7DD95802-9882-11CF-9FA9-00AA006C42C4";

        /// <summary> Registers a specific managed type as a folder home page. Returns a file path for the folder home page
        /// </summary>
        /// <param name="viewType">Type of the home page control. 
        /// Control must be ComVisible should be registered safe for scripting</param>
        /// <param name="folderName">Name of the folder.</param>
        /// <returns>file path to the folder home page</returns>
        public static string RegisterType(Type viewType, string folderName)
        {
            if (viewType == null) return null;

            // Create the Local App Data directory for the Web view files to reside in
            //string webViewDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), Properties.Resources.ViewsDirectory);
            //if (Directory.Exists(webViewDirectory) == false) Directory.CreateDirectory(webViewDirectory);

            // Create the web view file name based on the viewType guid in the web view directory
            string webViewFile = Path.Combine(BaseUnit.AppDirectory(BaseUnit.FolderType.ViewsFolder), viewType.GUID.ToString("N") + folderName + ".htm");

            // Open a file stream and text writer for the Web view stream
            using (FileStream stm = new FileStream(webViewFile, FileMode.OpenOrCreate, FileAccess.Write))
            using (TextWriter writer = new StreamWriter(stm, System.Text.Encoding.Unicode))
            {
                // Look to see if the viewType has an init method that takes a single Outlook App parameter
                System.Reflection.MethodInfo initInfo = viewType.GetMethod("Initialize", new Type[] { typeof(Outlook.Application), typeof(string) });

                // If the viewType doesn't have an Init method, just write out the html page header
                if (initInfo == null)
                {
                    writer.WriteLine("<html><body rightmargin = '0' leftmargin ='0' topmargin ='0' bottommargin = '0'>");
                }

                // If the viewType does have an Init method, write script to trap the Body.OnLoad event and call the Init method
                // passing in the window.external.OutlookApplication object as the parameter
                else
                {
                    writer.WriteLine("<html><head><style type=\"text/css\">body{overflow: hidden}</style></head>");
                    writer.WriteLine("<body rightmargin = '0' leftmargin ='0' topmargin ='0' bottommargin = '0' onload='OnBodyLoad()'>");
                    writer.WriteLine("<script>\n\tfunction OnBodyLoad()\n\t{\n\t\tvar oApp = window.external.OutlookApplication;");
                    writer.WriteLine("\t\t{0}.Initialize(oApp, '{1}');", viewType.Name, folderName);
                    writer.WriteLine("\t}\n</script>");
                }

                // Write out an object tag that loads up the viewType as a com object via its class id
                writer.WriteLine("<object classid='clsid:{0}' ID='{1}' VIEWASTEXT width='100%' height='100%'/>", viewType.GUID, viewType.Name);
                writer.WriteLine("</body></html>");

                // Close the file
                try
                {
                    writer.Close();
                    stm.Close();
                }
                catch (System.IO.IOException ex)
                {
                    System.Diagnostics.Debug.WriteLine("FAILED in::FolderHomepage::RegisterType " + ex.Message);
                }
            }

            return webViewFile;
        }

        /// <summary> Registers a managed type that's exposed for COM interop as safe for initializing and scripting
        /// </summary>
        /// <param name="comType">comType</param>
        public static void RegisterSafeForScripting(Type comType)
        {
            Guid clsid = comType.GUID;
            Guid interfaceSafeScripting = new Guid(CATIDSafeForScripting);
            Guid interfaceSafeForInitializing = new Guid(CATIDSafeForInitializing);

            ICatRegister reg = (ICatRegister)new ComComponentCategoriesManager();
            reg.RegisterClassImplCategories(ref clsid, 1, new Guid[] { interfaceSafeScripting });
            reg.RegisterClassImplCategories(ref clsid, 1, new Guid[] { interfaceSafeForInitializing });
        }

        /// <summary> Unregisters a managed type that's exposed for COM interop as safe for initializing and scripting
        /// </summary>
        /// <param name="comType">comType</param>
        public static void UnregisterSafeForScripting(Type comType)
        {
            Guid clsid = comType.GUID;
            Guid interfaceSafeScripting = new Guid(CATIDSafeForScripting);
            Guid interfaceSafeForInitializing = new Guid(CATIDSafeForInitializing);

            ICatRegister reg = (ICatRegister)new ComComponentCategoriesManager();
            reg.UnRegisterClassImplCategories(ref clsid, 1, new Guid[] { interfaceSafeScripting });
            reg.UnRegisterClassImplCategories(ref clsid, 1, new Guid[] { interfaceSafeForInitializing });
        }
    }
    /// <summary> Class registeration interface.
    /// </summary>
    [ComImport(), Guid("0002E012-0000-0000-C000-000000000046")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    interface ICatRegister
    {
        void RegisterCategories(int cCategories, IntPtr rgCategoryInfo);

        void UnRegisterCategories(int cCategories, IntPtr rgcatid);

        void RegisterClassImplCategories(
                [In()] ref Guid rclsid,
                int cCategories,
                [In(), MarshalAs(UnmanagedType.LPArray)] Guid[] rgcatid);

        void UnRegisterClassImplCategories(
                [In()] ref Guid rclsid,
                int cCategories,
                [In(), MarshalAs(UnmanagedType.LPArray)] Guid[] rgcatid);

        void RegisterClassReqCategories(
            [In()] ref Guid rclsid,
            int cCategories,
            [In(), MarshalAs(UnmanagedType.LPArray)] Guid[] rgcatid);

        void UnRegisterClassReqCategories(
            [In()] ref Guid rclsid,
            int cCategories,
            [In(), MarshalAs(UnmanagedType.LPArray)] Guid[] rgcatid);
    }

    /// <summary> Component registration class
    /// </summary>
    [ComImport(), Guid("0002E005-0000-0000-C000-000000000046")]
    public class ComComponentCategoriesManager
    {
    }
}
